module main

import os
import json
import net
import rand
import dialog
import ttytm.webview

struct Windows {
	icon   string
	title  string
	width  int
	height int
	hint   string
	debug  bool
}

struct Php {
	file                  string
	entrance              string
	address               string
	port                  string
	is_custom_instruction bool
	start_instruction     string
	stop_instruction      string
	auto_stop             bool
}

struct Config {
	windows Windows
	php     Php
}

enum Hint {
	// Width and height are default size.
	@none = C.WEBVIEW_HINT_NONE
	// Window size can not be changed by a user.
	fixed = C.WEBVIEW_HINT_FIXED
	// Width and height are minimum bounds.
	min   = C.WEBVIEW_HINT_MIN
	// Width and height are maximum bounds.
	max   = C.WEBVIEW_HINT_MAX
}

// 窗口hint
pub fn hint_val(h string) webview.Hint {
	match h {
		'auto' {
			return .@none
		}
		'fixed' {
			return .fixed
		}
		'min' {
			return .min
		}
		'max' {
			return .max
		}
		else {
			return .@none
		}
	}
}

// 随即端口
pub fn rand_port() !u16 {
	p := rand.int_in_range(2, 9999) or { return 9999 }
	return net.validate_port(p)!
}

// 获取端口
fn get_port(port string) !u16 {
	if port == '*' {
		return rand_port()!
	}
	return port.u16()
}

// 弹出消息窗口
fn win_alert(e &webview.Event) bool {
	str_arg := e.get_arg[string](0) or { '' }
	num_arg := e.get_arg[int](1) or { 0 }
	match num_arg {
		0 {
			return dialog.message(str_arg)
		}
		1 {
			return dialog.message(str_arg, buttons: .ok_cancel)
		}
		else {
			return dialog.message(str_arg, buttons: .yes_no)
		}
	}
}

// 打开文件框
fn win_file_dialog(e &webview.Event) string {
	f := dialog.file_dialog() or { '' }
	return f.str()
}

// 打开文件夹
fn win_open_dir(e &webview.Event) string {
	str_arg := e.get_arg[string](0) or { '' }
	f := dialog.FileOpenOptions{str_arg}
	p, _ := dialog.open_dir(f) or { return '' }
	return p
}

// 打开读取文件内容框
fn win_read_file_dialog(e &webview.Event) string {
	str_arg := e.get_arg[string](0) or { '' }
	f := dialog.FileOpenOptions{str_arg}
	p := dialog.read_file(f) or { 'false' }
	return p
}

// 打开保存文件内容框
fn win_save_file_dialog(e &webview.Event) bool {
	content := e.get_arg[string](0) or { '' }
	path := e.get_arg[string](1) or { '' }
	filename := e.get_arg[string](2) or { '' }
	f := dialog.FileSaveOptions{path, filename}
	dialog.save_file(content, f) or { return false }
	return true
}

// is_file 返回一个指示给定是否为文件。
fn win_is_file(e &webview.Event) bool {
	// path string
	path := e.get_arg[string](0) or { '' }
	return os.is_file(path)
}

// 将当前工作目录与给定的（如果是相对的）连接起来，并返回绝对路径表示
fn win_abs_path(e &webview.Event) string {
	// path string
	path := e.get_arg[string](0) or { '' }
	return os.abs_path(path)
}

// cache_dir返回可写用户特定文件夹的路径，该文件夹适用于写入非必要数据。
fn win_cache_dir(e &webview.Event) string {
	return os.cache_dir()
}

// getwd 返回当前目录的绝对路径。
fn win_getwd(e &webview.Event) string {
	return os.getwd()
}

// is_dir 返回一个指示给定是否为目录。
fn win_is_dir(e &webview.Event) bool {
	// path string
	path := e.get_arg[string](0) or { '' }
	return os.is_dir(path)
}

// read_bytes 返回从 中的文件读取的所有字节。
fn win_read_bytes(e &webview.Event) string {
	// path string
	path := e.get_arg[string](0) or { '' }
	f := os.read_bytes(path) or { return '' }
	return f.str()
}

// 重命名 将文件或文件夹从 重命名为 。使用 mv 以独立于平台的方式移动或重命名文件。
fn win_rename(e &webview.Event) bool {
	// src string, dst string
	src := e.get_arg[string](0) or { '' }
	dst := e.get_arg[string](1) or { '' }
	mut s := true
	os.rename(src, dst) or { s = false }
	return s
}

// rename_dir将文件夹重命名为 。使用 mv 以独立于平台的方式移动或重命名文件。
fn win_rename_dir(e &webview.Event) bool {
	// src string, dst string
	src := e.get_arg[string](0) or { '' }
	dst := e.get_arg[string](1) or { '' }
	mut s := true
	os.rename_dir(src, dst) or { s = false }
	return s
}

// rm 删除 中的文件。
fn win_rm(e &webview.Event) bool {
	// path string
	path := e.get_arg[string](0) or { '' }
	mut s := true
	os.rm(path) or { s = false }
	return s
}

// rmdir 删除指定的目录。
fn win_rmdir(e &webview.Event) bool {
	// path string
	path := e.get_arg[string](0) or { '' }
	mut s := true
	os.rmdir(path) or { s = false }
	return s
}

// rmdir_all以递归方式删除指定的目录。
fn win_rmdir_all(e &webview.Event) bool {
	// path string
	path := e.get_arg[string](0) or { '' }
	mut s := true
	os.rmdir_all(path) or { s = false }
	return s
}

// 将文件或文件夹从src复制到dst
fn win_cp(e &webview.Event) bool {
	// string
	src := e.get_arg[string](0) or { '' }
	// string
	dst := e.get_arg[string](1) or { '' }
	mut s := true
	os.cp(src, dst) or { s = false }
	return s
}

// 将递归复制到 ，可以选择覆盖中的文件或目录
fn win_cp_all(e &webview.Event) bool {
	// src string, dst string, overwrite bool
	src := e.get_arg[string](0) or { '' }
	dst := e.get_arg[string](1) or { '' }
	overwrite := e.get_arg[bool](2) or { false }

	mut s := true
	os.cp_all(src, dst, overwrite) or { s = false }
	return s
}

fn main() {
	// 获取json字符串
	data := os.read_file('./config.json')!
	// 转义json
	config_json := json.decode(Config, data)!

	// 创建窗口
	w := webview.create(debug: config_json.windows.debug)
	// 设置图标
	w.set_icon(config_json.windows.icon) or {}
	// 设置标题
	w.set_title(config_json.windows.title)
	// 设置大小
	w.set_size(config_json.windows.width, config_json.windows.height, hint_val(config_json.windows.hint))
	// 绑定
	w.bind('win_alert', win_alert)

	w.bind('win_file_dialog', win_file_dialog)

	w.bind('win_open_dir', win_open_dir)

	w.bind('win_read_file_dialog', win_read_file_dialog)

	w.bind('win_save_file_dialog', win_save_file_dialog)

	w.bind('win_is_file', win_is_file)

	w.bind('win_abs_path', win_abs_path)

	w.bind('win_cache_dir', win_cache_dir)

	w.bind('win_getwd', win_getwd)

	w.bind('win_is_dir', win_is_dir)

	w.bind('win_read_bytes', win_read_bytes)

	w.bind('win_rename', win_rename)

	w.bind('win_rename_dir', win_rename_dir)

	w.bind('win_rm', win_rm)

	w.bind('win_rmdir', win_rmdir)

	w.bind('win_rmdir_all', win_rmdir_all)

	w.bind('win_cp', win_cp)

	w.bind('win_cp_all', win_cp_all)

	// 获取端口号
	port := get_port(config_json.php.port)!

	// 获取当前端口号
	w.bind('win_get_port', fn [port] (e &webview.Event) string {
		return port.str()
	})

	// 运行php
	newname := config_json.php.file
	if newname.trim(' ') != '' {
		mut newargs := []string{}
		if config_json.php.is_custom_instruction {
			newargs << config_json.php.start_instruction.split(' ')
		} else {
			newargs << ['-S', '${config_json.php.address}:${''}', config_json.php.entrance]
		}
		mut p := os.new_process(newname)
		p.create_no_window = true
		// 设置参数
		p.set_args(newargs)
		p.run()
		// 设置nav
		w.navigate('http://${config_json.php.address}:${port}')
		// 运行
		w.run()
		// 结束php
		if config_json.php.auto_stop {
			p.signal_term()
		} else {
			os.system(config_json.php.stop_instruction)
		}
	} else {
		w.serve_static('./www', port: port)!
		// 运行
		w.run()
	}
	// 结束窗口
	w.destroy()
}
